// ===========================
// get the package we need
// ===========================
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var morgan = require('morgan');
var mongoose = require('mongoose');

var jwt = require('jsonwebtoken');
var config = require('./config');
var User = require('./app/models/user');

// cryptographically Secret
const crypto = require('crypto');
const salt = crypto.randomBytes(256);
//TODO: use sha256 to hash user password + salt, return hash result to store to database
//TODO: along with slat

// ==========================
// configuration
// ==========================
var port = process.env.PORT || 8080;
mongoose.connect(config.database);
app.set('superSecret', config.secret);

// use body parser so we can get info from POST and/or URL param
app.use(bodyParser.urlencoded({extended: false}));
app.use(bodyParser.json());

// use morgan to log request to the console
app.use(morgan('dev'));

//
app.get('/', function(req, res) {
    res.send('Hello! The API is at http://localhost:' + port +'/api');
});


//API ROUTES

//get an instance of the router for api routes
var apiRoutes = express.Router();

//TODO: route to authenticate a user
apiRoutes.post('/authenticate', function (req, res) {

    User.findOne({
        name: req.body.name
    }, function (err, user) {
        if (err) throw err;

        if (!user) {
            res.json({success: false, message: 'Authentication failed. User not found.'});
        } else if (user) {

            //check if password matches
            if (user.password != req.body.password) {
                res.json({success: false, message: 'Authentication failed. Password is not match.'});
            } else {
                const payload = {
                    admin: user.admin
                };

                var token = jwt.sign(payload, app.get('superSecret'), {
                    expiresIn: 60 * 60 * 24
                });

                res.json({
                    success: true,
                    message: 'Enjoy your token!',
                    token: token
                });
            }
        }
    });

});

//TODO: route middleware to verify a token
apiRoutes.use(function(req, res, next) {
    var token = req.body.token || req.query.token || req.headers['x-access-token'];

    if (token) {

        // verifies secret and checks exp
        jwt.verify(token, app.get('superSecret'), function(err, decoded) {
            if (err) {
                return res.json({success: false, message: 'Failed to authenticate token.'});
            } else {
                req.decoded = decoded;
                next();
            }
        });
    } else {

        // if there is no token return an error
        return res.status(403).send({
            success: false,
            message: 'No token provided.'
        });
    }
});

apiRoutes.get('/', function(req, res) {
    res.json({message: 'Welcome to the coolest API on earth!'});
});

apiRoutes.get('/users', function(req, res) {
    User.find({}, function(err, users) {
       res.json(users);
    });
});

app.use('/api', apiRoutes);


app.listen(port);
console.log('Magic happens at http://localhost:' + port);

//
app.get('/setup', function (req, res) {

    // create a sample user
    var nick = new User({
        name: 'Nick Cerminara',
        password: 'password',
        admin: true
    });

    // save the sample user
    nick.save(function (err) {
        if (err) throw err;

        console.log('User saved successfully');
        res.json({ success: true });
    });
});